home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / machack / Hacks97 / CrashBurn.sit / Crash & Burn / source code / Flames.cpp < prev    next >
C/C++ Source or Header  |  1997-06-27  |  7KB  |  307 lines

  1. #include "flames.h"
  2. #include <stdlib.h>
  3. #include <time.h>
  4.  
  5. #define        Max(x, y)        ((x) > (y) ? (x) : (y))
  6. #define        Min(x, y)        ((x) < (y) ? (x) : (y))
  7. #define     random(val)     (rand() % (val+1))
  8.  
  9.  
  10. FlameDataRecPtr MakeNewFlames (GrafPtr thePort, Rect *flameBounds,
  11.                                 short minFlameWidth, short maxFlameWidth,
  12.                                 double flameDensity, double fadeRate, 
  13.                                 short maxFPS, CTabHandle itsCLUT)
  14. /* Initialize a structure which contains all the data needed to */
  15. /* run the flame routines */
  16. {
  17.     CGrafPtr        itsOldPort;
  18.     GDHandle        itsOldDevice;
  19.     FlameDataRecPtr F = NULL;
  20.     double            DTemp;
  21.     OSErr            errCode;
  22.     RGBColor        RBlack = {0,0,0};
  23.     unsigned    int    s;
  24.     
  25.     // initialize the random number generator
  26.     s = (unsigned int) clock();
  27.     srand (s);
  28.  
  29.     F = (FlameDataRecPtr)NewPtrClear (sizeof(FlameDataRec));
  30.     
  31.     if (F)
  32.       {
  33.           F->flameTaskPtr = NULL;
  34.           F->flamePort = thePort;
  35.           F->density = flameDensity * 100;
  36.          F->fireCLUT = itsCLUT;
  37.          F->maxColor = (**itsCLUT).ctSize;
  38.          F->fadePerStep = fadeRate * F->maxColor;
  39.         
  40.         /* Set the frame rate */
  41.         DTemp = (double)60 / (double)maxFPS;
  42.         if ((int)(DTemp + 0.5) > (int)DTemp)
  43.           F->timePerFrame = (int)DTemp+1;
  44.         else
  45.           F->timePerFrame = (int)DTemp;        
  46.         F->timePerFrame = Max(1, F->timePerFrame);
  47.             
  48.         // We will draw on the whole buffer, but not copy the bottom line
  49.         F->offRect = *flameBounds;
  50.         F->fireRect = *flameBounds;
  51.         OffsetRect (&F->offRect, -F->offRect.left, -F->offRect.top);
  52.         F->copyRect = F->offRect;
  53.         F->copyRect.bottom -= 1;
  54.  
  55.         // Create the offscreen GWorld which the fire will be calculated on
  56.         errCode = NewGWorld(&F->DrawingArea,8,&F->offRect,F->fireCLUT,NULL, 0);
  57.         if (F->isValid = (errCode == noErr))
  58.           {
  59.             // lock the offscreen pixmap and get a pointer to its drawing area
  60.             F->offPixMap = GetGWorldPixMap(F->DrawingArea);
  61.             LockPixels (F->offPixMap);
  62.             
  63.             // set the dimensions of the buffer
  64.             F->BUF_HEIGHT = flameBounds->bottom - flameBounds->top;
  65.             F->BUF_WIDTH = flameBounds->right - flameBounds->left;
  66.             F->maxFlameWidth = maxFlameWidth;
  67.             F->minFlameWidth = minFlameWidth;
  68.             
  69.             // Get the address of our calculation buffer
  70.             F->basePixels = (unsigned char *)GetPixBaseAddr(F->offPixMap);
  71.             F->BitMapWidth = (**F->offPixMap).rowBytes & 0x7FFF;
  72.  
  73.             // clear the offscreen buffer
  74.             GetGWorld(&itsOldPort,&itsOldDevice);                
  75.             SetGWorld (F->DrawingArea, NULL);
  76.             RGBForeColor (&RBlack);
  77.             PaintRect (&F->offRect);
  78.             SetGWorld (itsOldPort, itsOldDevice);
  79.           }
  80.       }
  81.       
  82.     return F;
  83. }        
  84.  
  85.  
  86.  
  87.  
  88. void FreeFlames (FlameDataRecPtr *F)
  89. {
  90.     
  91.     if (*F)
  92.       {
  93.           if ((**F).flameTaskPtr)
  94.             {
  95.               DisposePtr((Ptr)(**F).flameTaskPtr);
  96.                 (**F).flameTaskPtr = NULL;
  97.             }
  98.             
  99.         if ((**F).isValid)
  100.           {
  101.               UnlockPixels ((**F).offPixMap);
  102.               DisposeGWorld((**F).DrawingArea);
  103.           }
  104.         
  105.         DisposePtr((Ptr)*F);
  106.         *F = NULL;
  107.       }
  108. }
  109.  
  110.  
  111. void ChangeFlameDensity (FlameDataRecPtr F, double newDensity)
  112. {
  113.     if (F)
  114.       F->density = newDensity * 100;
  115. }
  116.  
  117.  
  118. void ChangeFlameWidth (FlameDataRecPtr F, short newMinWidth, short newMaxWidth)
  119. {
  120.     if (F)
  121.       {
  122.           F->maxFlameWidth = newMaxWidth;
  123.           F->minFlameWidth = newMinWidth;
  124.       }
  125. }
  126.  
  127.  
  128. void ChangeFlameFadeRate (FlameDataRecPtr F, double newFadeRate)
  129. {
  130.     if (F)
  131.       F->fadePerStep = newFadeRate * F->maxColor;
  132. }
  133.  
  134.  
  135.  
  136. void ChangeFlameFPS (FlameDataRecPtr F, short newFPS)
  137. {
  138.     double    DTemp;
  139.     if (F)
  140.       {
  141.         DTemp = (double)60 / (double)newFPS;
  142.         if ((int)(DTemp + 0.5) > (int)DTemp)
  143.           F->timePerFrame = (int)DTemp+1;
  144.         else
  145.           F->timePerFrame = (int)DTemp;        
  146.       }
  147. }
  148.  
  149.  
  150.  
  151. void StartFlames (FlameDataRecPtr F)
  152. {
  153.     
  154.     F->burning = TRUE;
  155.  
  156.  
  157. }
  158.  
  159.  
  160.  
  161.  
  162. void StopFlames (FlameDataRecPtr F)
  163. {
  164.     F->burning = FALSE;
  165. }
  166.  
  167.  
  168.  
  169.  
  170. short StepFlames(FlameDataRecPtr register F)
  171. /* Step the fire by one frame, and return the amount of time remaining */
  172. /* before the next frame should be drawn (in ticks) */
  173. {
  174.       register unsigned char *traverse;
  175.     register    short    x, y;
  176.     register    short BUF_HEIGHT = F->BUF_HEIGHT, 
  177.                       BUF_WIDTH = F->BUF_WIDTH;
  178.     long        StartTime, Duration;
  179.     short step, color;
  180.     unsigned char *limit;
  181.     unsigned char *limit2;
  182.             
  183.     // if we have stopped burning, return 0; this will cause
  184.     // the VBL Task to terminate
  185.     if (!F->burning)
  186.       return 0;
  187.                 
  188.     StartTime = TickCount();
  189.     
  190.     // Transform current buffer
  191.     traverse = F->basePixels + F->BitMapWidth + 1;
  192.      for(y=1;y<BUF_HEIGHT;y++)
  193.        {
  194.         for(x=1;x<BUF_WIDTH-1;x++)
  195.             {
  196.                 *(traverse - F->BitMapWidth) = (*traverse +                    // x, y-1
  197.                                             *(traverse - 1) +                // x, y
  198.                                             *(traverse + 1) +                // x-1, y
  199.                                             *(traverse + F->BitMapWidth)) >> 2;// x+1, y
  200.     
  201.             *traverse = Max (*traverse - F->fadePerStep, 0);
  202.                       
  203.             traverse++;
  204.              }
  205.           traverse += (2 + F->BitMapWidth - BUF_WIDTH);
  206.          }
  207.   
  208.   
  209.     // Set new bottom lines with random white or black
  210.     traverse = F->basePixels + (long)F->BitMapWidth * ((long)BUF_HEIGHT - 2);
  211.     limit = F->basePixels + (long)F->BitMapWidth * ((long)BUF_HEIGHT - 1);
  212.     while (traverse < limit)
  213.       {
  214.           step = random(F->maxFlameWidth - F->minFlameWidth)+F->minFlameWidth;    
  215.           if (random(100) < F->density)
  216.             color = F->maxColor;
  217.           else
  218.             color = 0;
  219.           
  220.           limit2 = traverse+step;
  221.           while ((traverse < limit2) && (traverse < limit))
  222.             {
  223.               *traverse = *(traverse + F->BitMapWidth) = color;
  224.               traverse++;
  225.           }
  226.       }
  227.     
  228. //    static     long    count = 0;
  229.     
  230. //    count++;
  231. //    if((count % 10) == 0){
  232.                                           
  233.         CopyBits ((const BitMap *)*F->offPixMap, &F->flamePort->portBits, 
  234.                   &F->copyRect, &F->fireRect, srcCopy, NULL);
  235. //    }
  236.     
  237.     Duration = TickCount() - StartTime;
  238.             
  239.     return Max (1, F->timePerFrame - Duration);
  240. }
  241.  
  242.  
  243.  
  244.  
  245.  
  246. static void LockHandle(Handle    h)
  247. {
  248.     if(h){
  249.         HLock(h);
  250.     }
  251. }
  252.  
  253. static void UnlockHandle(Handle h)
  254. {
  255.     if(h){
  256.         HUnlock(h);
  257.     }
  258. }
  259.  
  260. static void    UnlockPixMap(PixMapHandle p)
  261. {
  262.     if(p){
  263.         UnlockHandle((Handle)p);
  264.         UnlockHandle((Handle)p[0]->pmTable);
  265.     }
  266. }
  267.  
  268. static void    LockPixMap(PixMapHandle    p)
  269. {
  270.     if(p){
  271.         LockHandle((Handle)p);
  272.         LockHandle((Handle)p[0]->pmTable);
  273.     }
  274. }
  275.  
  276. static void    LockPixPat(PixPatHandle p)
  277. {
  278.     if(p){
  279.         LockHandle((Handle)p);
  280.         LockPixMap(p[0]->patMap);
  281.         LockHandle((Handle)p[0]->patData);
  282.         LockHandle((Handle)p[0]->patXData);
  283.         LockHandle((Handle)p[0]->patXMap);
  284.     }
  285. }
  286.  
  287.  
  288. void    LockFlames(FlameDataRecPtr inFlames)
  289. {
  290.  
  291.     LockHandle((Handle)inFlames->DrawingArea->grafVars);
  292.     LockHandle((Handle)inFlames->DrawingArea->visRgn);
  293.     LockHandle((Handle)inFlames->DrawingArea->clipRgn);
  294.     LockPixPat(inFlames->DrawingArea->bkPixPat);
  295.     LockPixPat(inFlames->DrawingArea->pnPixPat);
  296.     LockPixPat(inFlames->DrawingArea->fillPixPat);
  297.  
  298.  
  299.     LockHandle((Handle)inFlames->fireCLUT);
  300.     LockPixMap(inFlames->offPixMap);
  301.     
  302.  
  303.  
  304. }
  305.  
  306.  
  307.